In order to execute computer software written in a high level language, there are two generally accepted means. The source code may be first compiled by using a compiler into the object code (machine executable instructions) which can then be executed on a specific hardware (or simulated hardware) platform. Examples of computer language which typically involve compilation are C or C++ and Fortran. Alternatively, the source code may be read by an interpreter, one line at a time, which directly causes the underlying hardware platform to carry out the instructions. LISP is one example of an interpreted computer language.
Some other computer program languages may be subject to a hybrid approach for achieving portability and performance. For example, Java™ has gained popularity as a computer language for producing “write once, run anywhere” software, in addition to its object oriented nature. (Java is a trademark of Sun Microsystems, Inc. in the United States, other countries, or both.) Java source code is first compiled into bytecode, an intermediate representation of the software, on any platform. This bytecode can then be taken to another platform for execution. At the second platform, Java byte-code is interpreted by a Java virtual machine, which supports Java components on the platform with basic Java functionality The interpretation process causes execution of the program to be slow. What has become widely available to improve the performance of Java code execution is to use a Java Just-in-Time compiler (JIT compiler). This compiler will then convert bytecode into native code which can be immediately executed on the platform. The term JIT is also used to describe any runtime compiler in a virtual machine, even if it is used selectively to compile some Java class methods while others are interpreted (see later).
The time required to execute native code instructions (i.e. programs) can be reduced by applying compiler optimizations. Common optimization techniques include inlining, loop unrolling, synchronization, and specialized methods for exception handling and virtual function calls. Furthermore, JIT compilers often determine the most performance-critical methods of the code and optimize heavily only those methods (Sun Microsystems. The Java HotSpot Virtual Machine v1.4.1. White paper, available at http://java.sun.com/products/hotspot/docs/whitepaper/Java_Hotspot_v1.4.1/Java_HSpot_WP_v1.4.1—1002—1.html). Additionally, a JIT compiler can offer a higher optimization granularity by providing several optimization levels and using these levels according to the perceived method “hotness” (Michael G. Burke, Jong-Deok Choi, Stephen Fink, David Grove, Michael Hind, Vivek Sarkar, Mauricio J. Serrano, V. C. Sreedhar, Harini Srinivasan, and John Whaley, “The Jalapeno Dynamic Optimizing Compiler for Java”, 1999 ACM Java Grande Conference, June 12-14). Of course, higher optimization levels take more time, but are expected to provide better performance.
The hotness of a Java method is usually determined relatively to the other methods of the application. If an application has a few hot-spots, they can easily be determined by an adaptive JIT compiler and optimized accordingly. However, some applications have a very flat execution profile with thousands of methods being more or less equally important. In such cases a JIT compiler cannot make discriminatory decisions and will have to spend a considerable amount of time compiling these methods (the alternative is to use fewer optimizations across the board, thus reducing compilation time, but adversely affecting the application's performance).
Despite improved code generation by the optimization techniques, the start-up (or initialization) time of a Java application is negatively impacted since this is the point when most of the compilation occurs. Large server-side applications that have thousands of methods which need to be compiled are especially susceptible to large start-up times. This invention addresses this problem and proposes a solution to reduce application initialization time while reducing the chances of affecting the runtime performance of the application.
Although the above is discussed in terms of a Java virtual machine, similar principles apply in the case of other environments.